#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include "poller_protocol.h"

#define MAX_USERNAME 36
#define perror2(s, e) fprintf(stderr, "%s: %s\n", s, strerror(e))


char answer[4];
char hostName[18];
int port;

void GenerateRandomString ( char *username );
void Vote ( void *argument );

int main ( int argc, char *argv[] )
{
	int numVotes;

	if(argc < 5)
	{
		printf("not enough arguments");
		return EXIT_FAILURE;
	}

	strcpy ( hostName, argv[1] );

	port = atoi ( argv[2] );	

	numVotes = atoi ( argv[3] );
	
	if ( strcmp ( argv[4], "YES" ) == 0 )
	{
		strcpy ( answer, "yes");
	}
	else
	{
		strcpy ( answer, "no");
	}

	srand ( time(NULL) );

	int i;
	pthread_t *threads = malloc ( sizeof(pthread_t) * numVotes );

	for ( i = 0; i < numVotes; i++ )
	{
		int error;
		if ( error = pthread_create ( &threads[i], NULL, Vote, &i ) )
		{
			perror2("pthread_create", error);
		}		
	}

	for ( i = 0; i < numVotes; i++ )
	{
		int error, returnValue;

		if (error = pthread_join(threads[i], &returnValue ) ) 
		{
                         perror2("pthread_join", error);
		}

		if ( returnValue == EXIT_SUCCESS )
		{
			printf ( "Thread %d voted successfuly\n", i );
		}
		else
		{
			printf ( "Thread %d encountered a problem\n", i );
		}
	}
}

void Vote ( void *argument )
{
	/* Connect to server */

	struct sockaddr_in server;
	struct sockaddr *serverptr;
	int serverlen, sock;
	struct hostent *rem;

	if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
	{
		perror("socket");
		pthread_exit ( EXIT_FAILURE );
	}
	if((rem = gethostbyname(hostName)) == NULL)
	{
		perror("gethostbyname");
		pthread_exit ( EXIT_FAILURE );
	}
	bcopy((char *) rem->h_addr, (char *) &server.sin_addr, rem->h_length);
	server.sin_family = PF_INET;
	server.sin_port = htons(port);
	serverptr = (struct sockaddr *) &server;
	serverlen = sizeof(server);

	if(connect(sock, serverptr, serverlen) < 0)
	{
		perror("connect");
		pthread_exit ( EXIT_FAILURE );
	}

	int header;
	char message[MESSAGE_SIZE];
	char username[MESSAGE_SIZE];

	if ( Wait ( MENU, message, sock ) == false )
	{
		close ( sock );
		pthread_exit ( EXIT_FAILURE );
	}

	if ( Send ( VOTE_BEGIN, "no payload", sock ) == false )
	{
		close ( sock );
		pthread_exit ( EXIT_FAILURE );
	}

	if ( Wait ( CREDENTIALS_REQUEST, message, sock ) == false )
	{
		close ( sock );
		pthread_exit ( EXIT_FAILURE );
	}

	GenerateRandomString ( username );

	if ( Send (  CREDENTIALS_RESPONSE, username, sock ) == false )		
	{
		close ( sock );
		pthread_exit ( EXIT_FAILURE );
	}

	if ( WaitResponse ( &header, message, sock ) == false )
	{
		close ( sock );
		pthread_exit ( EXIT_FAILURE );
	}

	switch ( header )
	{
		case VOTE_SUBJECT:
			if ( Send ( VOTE, answer, sock ) == false )
			{
				close ( sock );
				pthread_exit ( EXIT_FAILURE );
			}

			if ( Wait ( VOTE_REGISTERED, message, sock ) == false )
			{
				close ( sock );
				pthread_exit ( EXIT_FAILURE );
			}
			break;
		case ERROR_VOTE_AGAIN:
			printf ( "Username %s exists\n", username );		
			break;
	}

	if ( Send ( QUIT_CONNECTION, "no payload", sock ) == false )
	{
		close ( sock );
		pthread_exit ( EXIT_FAILURE );
	}

	close ( sock );
	pthread_exit ( EXIT_SUCCESS );
}


void GenerateRandomString ( char *username ) 
{
	int i, lenght;
	
	lenght = rand () % MAX_USERNAME + 2;
	
	for ( i = 0; i < lenght; i++ )
	{
		username[i] = ( rand() % (122 - 65) ) + 65;
	}
	username[lenght] = '\0';
}









